package com.fullstack.app

import cats.effect.IO
import cats.effect.IO.asyncForIO
import org.scalajs.dom.{console, document, window}
import tyrian.Html.*
import tyrian.cmds.Logger
import tyrian.*

import scala.scalajs.js.annotation.*
import com.fullstack.app.App.AppMsg.*
import com.fullstack.app.App.{Model, Msg}
import com.fullstack.app.pages.Page
import com.fullstack.app.pages.core.Session


@JSExportTopLevel("App")
class App extends TyrianIOApp[Msg, Model] {
  //  message, model=state

  /**
   * We can send message by
   *    trigger a command
   *    create a subscription
   *    listening for a event
   *
   */
    
  override def init(flags: Map[String, String]): (Model, Cmd[IO, Msg]) =

    val location = window.location.pathname
    console.log(location)
    val page = Page.getPage(location)
    val pageCmd = page.initCmd

    val session = Session()
    val sessionCmd = session.initCmd

    (Model(session, page), pageCmd |+| sessionCmd)

  // model can change by receiving messages: model + message -> mew model
  // update triggered whenever we get a new message
  override def update(model: Model): Msg => (Model, Cmd[IO, Msg]) =

    case FollowInternalLink(location) =>

      val loc = Location.fromUrl(location, Location.fromJsLocation(window.location))

      val newPage = Page.getPage(loc.locationDetails.pathName)
      val newPageCmd = newPage.initCmd

      (model.copy(page = newPage), newPageCmd |+| Nav.pushUrl(loc.href)  )

    case FollowExternalLink(location) =>
      (model, Nav.loadUrl(location))

    case msg: Session.SessionMsg =>
      val (newSession, cmd) = model.session.update(msg)
      (model.copy(session = newSession), cmd)

    case msg: App.Msg =>
      val (newPage, cmd) = model.page.update(msg)
      (model.copy(page = newPage), cmd)

  // view triggered whenever model changes
  override def view(model: Model): Html[Msg] =
    div(`class`:="")(
      model.page.view()
    )

  // potentially endless stream of messages
  override def subscriptions(model: Model): Sub[IO, Msg] =
    model.page.subscriptions()

  override def router: Location => Msg =
    Routing.basic(FollowInternalLink.apply, FollowExternalLink.apply)


}


object App {

  trait Msg
  
  enum AppMsg extends Msg:
    case NoOp
    case ShowLogin
    case FollowInternalLink(location: String)
    case FollowExternalLink(location: String)
    case HomeGoTo(pageUrl: String)


  case class Model(session: Session, page: Page) // router: Router,

  // 开发dev
  val root = "http://127.0.0.1:4046"
  // 生产部署prod
//  val root = "/api"

}